package ua.edu.nuos.jeetraining2012.cms.util.svn;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ua.edu.nuos.jeetraining2012.cms.util.svn.exception.SvnException;

import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

/**
 * Created with IntelliJ IDEA.
 * User: artur
 * Date: 28.06.13
 * Time: 12:15
 * To change this template use File | Settings | File Templates.
 */
public class SvnServeConf {

    /**
     * Define logger.
     */
    final static private Logger logger = LoggerFactory.getLogger(SvnServeConf.class);

    private final String PATHTOREPO = RepositoryProperties.getPath();


    public void changeDefaultSettings(String repo) throws SvnException, IOException {
        logger.debug("Method changeDefaultSettings() - invocation");

        File svnserve = new File(PATHTOREPO + repo + "/conf/svnserve.conf");


        changeSvnserve(svnserve, repo);
        writeAuthz(repo, new HashMap<String, String>());
        writePasswords(repo, new HashMap<String, String>());

        logger.debug("Method changeDefaultSettings() - finish");
    }

    private void changeSvnserve(File svnserve, String repo) throws SvnException {
        logger.debug("Method changeSvnserve() - invocation");

        ArrayList<String> content = replaceDefault(readConfFile(svnserve), repo);
        if (!content.isEmpty()) {
            writeFileConf(content, svnserve);
        }

        logger.debug("Method changeSvnserve() - finish");
    }


    /**
     * Method read default settings of configuration SVN
     *
     * @param file
     * @return
     * @throws SvnException
     */
    private ArrayList<String> readConfFile(File file) throws SvnException {
        ArrayList<String> content;
        try {
            BufferedReader bufReader = new BufferedReader(new FileReader(file));
            content = new ArrayList<>();

            while (bufReader.ready()) {
                content.add(bufReader.readLine());
            }

            bufReader.close();
        } catch (FileNotFoundException e) {
            System.out.println("FileNotFoundException - " + e.getMessage());
            throw new SvnException("FileNotFoundException - " + e.getMessage());
        } catch (IOException e) {
            System.out.println("IOException - " + e.getMessage());
            throw new SvnException("IOException - " + e.getMessage());
        }
        return content;
    }

    private void writeFileConf(ArrayList<String> content, File file) throws SvnException {
        try {
            BufferedWriter bufWriter = new BufferedWriter(new FileWriter(file));

            for (String line : content) {
                bufWriter.write(line + "\n");
            }

            bufWriter.close();

        } catch (IOException e) {
            System.out.println("IOException - " + e.getMessage());
            throw new SvnException("IOException - " + e.getMessage());
        }

    }


    /**
     * Method rewrite default authorization rules to access user to their repositories
     *
     * @param content
     * @param repo
     * @return
     */
    private ArrayList<String> replaceDefault(ArrayList<String> content, String repo) {
        logger.debug("Method replaceDefault() - invocation");

        int count = 0;
        for (String line : content) {

            if (line.equals("# anon-access = read")) {
                content.set(count, "anon-access = none");
            }

            if (line.equals("# password-db = passwd")) {
                content.set(count, "password-db = passwd");
            }

            if (line.equals("# authz-db = authz")) {
                content.set(count, "authz-db = authz");
            }

            if (line.equals("# realm = My First Repository")) {
                content.set(count, "realm = " + repo);
            }

            count++;
        }

        logger.debug("Method replaceDefault() - finish with {}", content);
        return content;
    }


    /**
     * Method write rights to file "authz" to access users to theirs hoot folders
     *
     * @param repo   string name of repository
     * @param rights collection with  k - user, v - password that must be added to authz file
     * @throws IOException
     */
    public boolean writeAuthz(String repo, Map<String, String> rights) {
        logger.debug("writeAuthz() - invocation with Map {}", rights);

        File authz = new File(PATHTOREPO + repo + "/conf/authz");
        BufferedWriter bufWriter;

        try {
            bufWriter = new BufferedWriter(new FileWriter(authz));

            bufWriter.write("[groups]"+"\n");
            bufWriter.write("admins = admin"+"\n\n");
            bufWriter.write("[/]"+"\n");
            bufWriter.write("@admins = rw"+"\n\n");

            for (Map.Entry<String, String> entry : rights.entrySet()) {
                bufWriter.write("[/" + entry.getKey() + "]" + "\n");
                bufWriter.write("@admins = rw" + "\n");
                bufWriter.write(entry.getKey() + " = rw" + "\n");
                bufWriter.write("* =" + "\n\n");
            }

            bufWriter.close();
            writePasswords(repo, rights);

            logger.debug("writeAuthz() - finish");
            return true;
        } catch (IOException e) {
            logger.warn("updateUserRights() - finish with IOException {}", e.getMessage());
            return false;
        }
    }

    /**
     * Method write Default user "admin" with this password and other users, if necessary in format
     * user = password in file passwd of configuration SVN
     *
     * @param repo   string name of repository
     * @param rights collection with  k - user, v - password that must be added to passwd
     * @throws IOException IOException if produced errors with work in File System
     */
    public void writePasswords(String repo, Map<String, String> rights) throws IOException {
        File passwd = new File(PATHTOREPO + repo + "/conf/passwd");
        Map<String, String> admin = RepositoryProperties.getAdmin();

        BufferedWriter bufWriter = new BufferedWriter(new FileWriter(passwd));
        bufWriter.write("[users]\n");
        bufWriter.write(admin.get("name") + " = " + admin.get("passwd") + "\n");

        for (Map.Entry<String, String> entry : rights.entrySet()) {
            bufWriter.write(entry.getKey() + " = " + entry.getValue() + "\n");
        }

        bufWriter.close();
    }
}
